import React, {
  PureComponent,
  Children,
  useEffect,
  useState,
  useImperativeHandle,
  forwardRef,
} from "react";
import "./index.less";
import Swiper from "swiper/swiper-bundle.js";
import "swiper/swiper-bundle.css";
import PropTypes from "prop-types";

export default class Tabs extends PureComponent {
  navRef = null;

  courselRef = React.createRef(null);

  constructor(props) {
    super(props);
    this.state = { active: 0 };
    this.handleClickItem = this.handleClickItem.bind(this);
  }

  componentDidMount() {
    let { hasBarAnimation } = this.props;
    this.moveBottomBar();
    // 不需要条的动画，就不加transition
    if (hasBarAnimation)
      requestAnimationFrame(() => {
        this.navRef.querySelector(".b-tabs-nav__bottom-bar").style.transition =
          "0.3s ease-in";
      });
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    // 如果给外层可以传递状态的可能
    if (nextProps.active !== undefined) {
      return {
        active: nextProps.active,
      };
    }
    return null;
  }

  /**
   * 处理tab的点击事件
   * @param {*} index  tab的索引或者key
   * @param {*} hasClickTab 是否需要点击tab的时候滑动内容
   */
  handleClickItem(index, hasClickTab) {
    this.setState({ active: index }, () => {
      if (hasClickTab && this.props.canSlide)
        this.courselRef.current.slideTo(this.state.active + 1);

      let navCWidth = this.navRef.clientWidth;
      let activeItem = this.navRef.querySelector(".b-tabs-nav__item--active");
      //itme要移动到的距左边的距离
      let targetLeft =
          activeItem.offsetLeft - navCWidth / 2 + activeItem.clientWidth / 2,
        wait = 1000 / 30;

      let timer = setInterval(() => {
        this.navRef.scrollLeft =
          this.navRef.scrollLeft +
          Math.ceil((targetLeft - this.navRef.scrollLeft) / 2);
        if (this.navRef.scrollLeft >= targetLeft) {
          this.navRef.scrollLeft = targetLeft;
          clearInterval(timer);
        }
      }, wait);
      //移动底部的条
      this.moveBottomBar(activeItem);
    });
  }

  /**
   * 移动条
   * @param {*} activeItem 活动中的tab节点
   */
  moveBottomBar(activeItem) {
    let { aside } = this.props;
    let bottomBar = this.navRef.querySelector(".b-tabs-nav__bottom-bar");
    let item =
      activeItem || this.navRef.querySelector(".b-tabs-nav__item--active");

    // 是否侧边栏tab
    if (aside)
      bottomBar.style.top =
        item.offsetTop +
        (item.clientHeight / 2 - bottomBar.clientHeight / 2) +
        "px";
    else
      bottomBar.style.left =
        item.offsetLeft +
        (item.clientWidth / 2 - bottomBar.clientWidth / 2) +
        "px";
  }

  render() {
    let { active } = this.state;
    let { children, onTabClick, canSlide, aside, bottomBar } = this.props;

    return (
      <div className={`b-tabs ${aside ? "b-tabs--aside" : ""}`}>
        <div className="b-tabs-nav" ref={(r) => (this.navRef = r)}>
          <div className="b-tabs-nav__wrap">
            {Children.map(children, (tab, i) => {
              return (
                <div
                  className={`b-tabs-nav__item ${
                    active === i ? "b-tabs-nav__item--active" : ""
                  }`}
                  onClick={() => {
                    this.handleClickItem(i, true);
                    onTabClick && onTabClick();
                  }}
                >
                  {tab.props.title}
                </div>
              );
            })}
            {bottomBar ? (
              React.cloneElement(bottomBar, {
                ...bottomBar.props,
                className:
                  "b-tabs-nav__bottom-bar " + (bottomBar.className || ""),
              })
            ) : (
              <div className="b-tabs-nav__bottom-bar"></div>
            )}
          </div>
        </div>

        <div className="b-tabs-content">
          {/* 控制是否需要滑动内容 */}
          {canSlide ? (
            <Coursel
              ref={this.courselRef}
              aside={aside}
              slideChangeItem={this.handleClickItem}
            >
              {children}
            </Coursel>
          ) : (
            Children.map(children, (tab, index) => {
              return (
                <div style={{ display: active === index ? "block" : "none" }}>
                  {tab}
                </div>
              );
            })
          )}
        </div>
      </div>
    );
  }
}

Tabs.propTypes = {
  onTabClick: PropTypes.func,
  canSlide: PropTypes.bool,
  aside: PropTypes.bool,
  bottomBar: PropTypes.element,
  hasBarAnimation: PropTypes.bool,
};
Tabs.defaultProps = {
  canSlide: false,
  aside: false,
  hasBarAnimation: true,
};

/**
 * 类组件使用函数组件的ref要用forwardRef传递才可以
 */
const Coursel = forwardRef(function (
  { children, slideChangeItem, aside },
  ref
) {
  const [swiper, setSwiper] = useState({});

  useImperativeHandle(ref, () => {
    return {
      slideTo: (active) => {
        swiper.slideTo(active);
      },
    };
  });

  useEffect(() => {
    setSwiper(
      new Swiper(".b-swiper-container", {
        loop: true,
        centeredSlides: true,
        direction: aside ? "vertical" : "horizontal",
        on: {
          transitionStart() {
            slideChangeItem && slideChangeItem(this.activeIndex - 1);
          },
        },
      })
    );
    return () => {
      setSwiper(null);
    };
    // aside更新的时候也更新下swiper，理论上不需要动态更新swiper的属性
  }, [aside]);

  return (
    <div className="b-swiper-container">
      <div className="swiper-wrapper">
        {Children.map(children, (tab, i) => {
          return (
            <div
              className="swiper-slide"
              key={i}
              style={{ padding: "10px", height: "100px", textAlign: "center" }}
              onTouchStart={(e) => {}}
            >
              {tab.props.children}
            </div>
          );
        })}
      </div>
      <div className="swiper-pagination"></div>
    </div>
  );
});
